<div class="chapter" id="chapter.Android"
     xmlns="http://www.w3.org/1999/xhtml">

    <div class="title">Cling on Android</div>
    <div class="content">

        <p>
            Cling Core provides a UPnP stack for Android applications. Typically you'd write control point applications,
            as most Android systems today are small hand-held devices. You can however also write UPnP server
            applications on Android, all features of Cling Core are supported.
        </p>

        <p>
            Android platform level 15 (4.0) is required for Cling 2.x, use Cling 1.x to support older Android versions.
        </p>

        <div class="note">
            <div class="title">Cling on the Android emulator</div>
            At the time of writing, receiving UDP Multicast datagrams was not supported by the Android emulator. The
            emulator will send (multicast) UDP datagrams, however. You will be able to send a multicast UPnP search and
            receive UDP unicast responses, therefore discover existing running devices. You will not discover devices
            which have been turned on after your search, and you will not receive any message when a device is switched
            off. Other control points on your network will not discover your local Android device/services at all. All
            of this can be confusing when testing your application, so unless you really understand what works and what
            doesn't, you might want to use a real device instead.
        </div>

        <p>
            The following examples are based on the Cling demo applications for Android, the
            <code>cling-demo-android-browser</code> and the <code>cling-demo-android-light</code>, available in the
            Cling distribution.
        </p>

        <div class="section" id="section.Android.ConfiguringService">
            <div class="title">Configuring the application service</div>
            <div class="content">

                <p>
                    You could instantiate the Cling <code>UpnpService</code> as usual in your Android application's
                    main activity. On the other hand, if several activities in your application require access to the
                    UPnP stack, a better design would utilize a background <code>android.app.Service</code>. Any
                    activity that wants to access the UPnP stack can then bind and unbind from this service as needed.
                </p>

                <p>
                    The interface of such a service component is available in Cling as
                    <code>org.fourthline.cling.android.AndroidUpnpService</code>:
                </p>

                <a class="citation"
                   href="javacode://org.fourthline.cling.android.AndroidUpnpService"
                   style="include:CLASS;"/>

                <p>
                    An activity typically accesses the <code>Registry</code> of known UPnP devices or searches for and
                    controls UPnP devices with the <code>ControlPoint</code>.
                </p>

                <p>
                    You have to configure the built-in implementation of this service component in your
                    <code>AndroidManifest.xml</code>, along with various required permissions:
                </p>

                <a class="citation"
                   href="file://AndroidManifest.xml"/>

                <p>
                    If a WiFi interface is present, Cling requires access to the interface. Cling will automatically
                    detect when network interfaces are switched on and off and handle this situation gracefully: Any
                    client operation will result in a "no response from server" state when no network is available.
                    Your client code has to handle such a situation anyway.
                </p>

                <p>
                    Cling uses a custom configuration on Android, the <code>AndroidUpnpServiceConfiguration</code>,
                    utilizing the Jetty transport and the <code>Recovering*</code> XML parsers and processors. See the
                    Javadoc of the class for more information.
                </p>

                <p>
                    <em>Jetty 8 libraries are required to use Cling on Android, see the demo applications for Maven
                        dependencies!</em>
                </p>

                <p>
                    For example, these dependencies are usually required in a Maven POM for Cling to work on Android:
                </p>

                <pre><![CDATA[<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>${jetty.version}</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlet</artifactId>
    <version>${jetty.version}</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-client</artifactId>
    <version>${jetty.version}</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>${slf4j.version}</version>
</dependency>]]></pre>

                <p>
                    The service component starts and stops the UPnP system when the service component is created and
                    destroyed. This depends on how you access the service component from within your activities.
                </p>

            </div>
        </div>

        <div class="section" id="section.Android.BindService">
            <div class="title">Accessing the service from an activity</div>
            <div class="content">

                <p>
                    The lifecycle of service components in Android is well defined. The first activity which binds to a
                    service will start the service if it is not already running. When no activity is bound to the
                    service any more, the operating system will destroy the service.
                </p>

                <p>
                    Let's write a simple UPnP browsing activity. It shows all devices on your network in a list and it
                    has a menu option which triggers a search action. The activity connects to the UPnP service and then
                    listens to any device additions or removals in the <code>Registry</code>, so the displayed list of
                    devices is kept up-to-date:
                </p>

                <a class="citation"
                   href="javacode://org.fourthline.cling.demo.android.browser.BrowserActivity"
                   style="include:CLASS, CLASS_END, SERVICE_BINDING;"/>

                <p>
                    We utilize the default layout provided by the Android runtime and the <code>ListActivity</code>
                    superclass. Note that this activity can be your applications main activity, or further up
                    in the stack of a task. The <code>listAdapter</code> is the glue between the device additions
                    and removals on the Cling <code>Registry</code> and the list of items shown in the user interface.
                </p>

                <div class="note">
                    <div class="title">Debug logging on Android</div>
                    <p>
                        Cling uses the standard JDK logging, <code>java.util.logging</code>. Unfortunately, by default
                        on Android you will not see <code>FINE</code>, <code>FINER</code>, and <code>FINEST</code> log
                        messages, as their built-in log handler is broken (or, so badly designed that it might as well
                        be broken). The easiest workaround is to set a custom log handler available in the
                        <code>FixedAndroidLogHandler</code> class.
                    </p>
                </div>

                <p>
                    The <code>upnpService</code> variable is <code>null</code> when no backend service is bound to this
                    activity. Binding and unbinding occurs in the <code>onCreate()</code> and <code>onDestroy()</code>
                    callbacks, so the activity is bound to the service as long as it is alive.
                </p>

                <p>
                    Binding and unbinding the service is handled with the <code>ServiceConnection</code>:
                    On connect, first a listener is added to the <code>Registry</code> of the UPnP service. This
                    listener will process additions and removals of devices as they are discovered on your network, and
                    update the items shown in the user interface list. The <code>BrowseRegistryListener</code> is
                    removed when the activity is destroyed.
                </p>

                <p>
                    Then any already discovered devices are added manually to the user interface, passing them
                    through the listener. (There might be none if the UPnP service was just started and no device
                    has so far announced its presence.) Finally, you start asynchronous discovery by sending a
                    search message to all UPnP devices, so they will announce themselves. This search message is
                    NOT required every time you connect to the service. It is only necessary once, to populate the
                    registry with all known devices when your (main) activity and application starts.
                </p>

                <p>
                    This is the <code>BrowseRegistryListener</code>, its only job is to update the
                    displayed list items:
                </p>

                <a class="citation"
                   href="javacode://org.fourthline.cling.demo.android.browser.BrowserActivity.BrowseRegistryListener"/>

                <p>
                    For performance reasons, when a new device has been discovered, we don't wait until a fully hydrated
                    (all services retrieved and validated) device metadata model is available. We react as quickly as
                    possible and don't wait until the <code>remoteDeviceAdded()</code> method will be called. We display
                    any device even while discovery is still running. You'd usually not care about this on a desktop
                    computer, however, Android handheld devices are slow and UPnP uses several bloated XML descriptors
                    to exchange metadata about devices and services. Sometimes it can take several seconds before a
                    device and its services are fully available. The <code>remoteDeviceDiscoveryStarted()</code> and
                    <code>remoteDeviceDiscoveryFailed()</code> methods are called as soon as possible in the discovery
                    process. On modern fast Android handsets, and unless you have to deal with dozens of UPnP devices
                    on a LAN, you don't need this optimization.
                </p>

                <p>
                    By the way, devices are equal (<code>a.equals(b)</code>) if they have the same UDN, they might not
                    be identical (<code>a==b</code>).
                </p>

                <p>
                    The <code>Registry</code> will call the listener methods in a separate thread. You have to update
                    the displayed list data in the thread of the user interface.
                </p>

                <p>
                    The following methods on the activity add a menu with a search action, so a user can refresh the
                    list manually:
                </p>

                <a class="citation"
                   id="org.fourthline.cling.demo.android.browser.BrowserActivity_menu"
                   href="javacode://org.fourthline.cling.demo.android.browser.BrowserActivity"
                   style="include:CLASS, CLASS_END, MENU; exclude: OPTIONAL;"/>

                <p>
                    Finally, the <code>DeviceDisplay</code> class is a very simple JavaBean that only provides a
                    <code>toString()</code> method for rendering the list. You can display any information about UPnP
                    devices by changing this method:
                </p>

                <a class="citation"
                   href="javacode://org.fourthline.cling.demo.android.browser.BrowserActivity.DeviceDisplay"
                   style="exclude: DETAILS;"/>

                <p>
                    We have to override the equality operations as well, so we can remove and add devices from the list
                    manually with the <code>DeviceDisplay</code> instance as a convenient handle.
                </p>

                <p>
                    So far we have implemented a UPnP control point, next we create a UPnP device with services.
                </p>

            </div>
        </div>

        <div class="section" id="section.Android.LocalDevice">
            <div class="title">Creating a UPnP device</div>

            <p>
                The following activity provides a UPnP service, the well known <em>SwitchPower:1</em> with a
                <em>BinaryLight:1</em> device:
            </p>

            <a class="citation"
               href="javacode://org.fourthline.cling.demo.android.light.LightActivity"
               style="include:CLASS, CLASS_END, SERVICE_BINDING; exclude: LOGGING;"/>

            <p>
                When the UPnP service is bound, for the first time, we check if the device has already been created by
                querying the <code>Registry</code>. If not, we create the device and add it to the
                <code>Registry</code>.
            </p>

            <div class="note">
                <div class="title">Generating a stable UDN on Android</div>
                <p>
                    The UDN of a UPnP device is supposed to be stable: It should not change between restarts of the
                    device. Unfortunately, the Cling helper method <code>UDN.uniqueSystemIdentifier()</code> doesn't
                    work on Android, see its Javadoc. Generating a new UUID every time your activity starts might
                    be OK for testing, in production you should generate a UUID once when your application starts for
                    the first time and store the UUID value in your application's preferences.
                </p>
            </div>

            <p>
                The activity is also a JavaBean <code>PropertyChangeListener</code>, registered with
                <code>SwitchPower</code> service. Note that this is JavaBean eventing, it has nothing to do with UPnP
                GENA eventing! We monitor the state of the service and switch the UI accordingly, turning the light on
                and off:
            </p>

            <a class="citation"
               href="javacode://org.fourthline.cling.demo.android.light.LightActivity"
               id="org.fourthline.cling.demo.android.light.LightActivity_propertyChange"
               style="include:CLASS, CLASS_END, PROPERTY_CHANGE;"/>

            <p>
                The <code>createDevice()</code> method simply instantiates a new <code>LocalDevice</code>:
            </p>

            <a class="citation"
               href="javacode://org.fourthline.cling.demo.android.light.LightActivity"
               id="org.fourthline.cling.demo.android.light.LightActivity_createDevice"
               style="include:CLASS, CLASS_END, CREATE_DEVICE;"/>

            <p>
                For the <code>SwitchPower</code> class, again note the dual eventing for JavaBeans and UPnP:
            </p>

            <a class="citation"
               href="javacode://org.fourthline.cling.demo.android.light.SwitchPower"
               style="include:CLASS"/>

        </div>

        <div class="section" id="section.Android.Optimize">
            <div class="title">Optimizing service behavior</div>
            <div class="content">

                <p>
                    The UPnP service consumes memory and CPU time while it is running. Although this is typically not an
                    issue on a regular machine, this might be a problem on an Android handset. You can preserve memory
                    and handset battery power if you disable certain features of the Cling UPnP service, or if you even
                    pause and resume it when appropriate.
                </p>

                <p>
                    Furthermore, some Android handsets do not support multicast networking (HTC phones, for example), so
                    you have to configure Cling accordingly on such a device and disable most of the UPnP discovery
                    protocol.
                </p>

                <div class="section" id="section.Android.Optimize.MaintainRegistry">
                    <div class="title">Tuning registry maintenance</div>
                    <div class="content">

                        <p>
                            There are several things going on in the background while the service is running. First,
                            there is the registry of the service and its maintenance thread. If you are writing a
                            control point, this background registry maintainer is going to renew your outbound GENA
                            subscriptions with remote services periodically. It will also expire and remove any
                            discovered remote devices when the drop off the network without saying goodbye. If you are
                            providing a local service, your device announcements will be refreshed by the registry
                            maintainer and inbound GENA subscriptions will be removed if they haven't been renewed in
                            time. Effectively, the registry maintainer prevents stale state on the UPnP network, so all
                            participants have an up-to-date view of all other participants, and so on.
                        </p>

                        <p>
                            By default the registry maintainer will run every second and check if there is something to
                            do (most of the time there is nothing to do, of course). The default Android configuration
                            however has a default sleep interval of three seconds, so it is already consuming less
                            background CPU time - while your application might be exposed to somewhat outdated
                            information. You can further tune this setting by overriding the
                            <code>getRegistryMaintenanceIntervalMillis()</code> in the
                            <code>UpnpServiceConfiguration</code>. On Android, you have to subclass the
                            service implementation to provide a new configuration:
                        </p>

                        <a class="citation"
                           href="javacode://org.fourthline.cling.demo.android.browser.BrowserUpnpService"
                           style="include:CLASS; exclude: SERVICE_TYPE;"/>

                        <p>
                            Don't forget to now configure <code>BrowserUpnpService</code> in your
                            <code>AndroidManifest.xml</code> instead of the original implementation. You also have to
                            use this class when binding to the service in your activities instead of
                            <code>AndroidUpnpServiceImpl</code>.
                        </p>
                    </div>

                </div>

                <div class="section" id="section.Android.Optimize.PauseRegistry">
                    <div class="title">Pausing and resuming registry maintenance</div>
                    <div class="content">

                        <p>
                            Another more effective but also more complex optimization is pausing and resuming the
                            registry whenever your activities no longer need the UPnP service. This is typically the
                            case when an activity is no longer in the foreground (paused) or even no longer visible
                            (stopped). By default any activity state change has no impact on the state of the UPnP
                            service unless you bind and unbind from and to the service in your activities
                            lifecycle callbacks.
                        </p>

                        <p>
                            In addition to binding and unbinding from the service you can also pause its registry by
                            calling <code>Registry#pause()</code> when your activity's <code>onPause()</code> or
                            <code>onStop()</code> method is called. You can then resume the background service
                            maintenance (thread) with <code>Registry#resume()</code>, or check the status with
                            <code>Registry#isPaused()</code>.
                        </p>

                        <p>
                            Please read the Javadoc of these methods for more details and what consequences pausing
                            registry maintenance has on devices, services, and GENA subscriptions. Depending on what
                            your application does, this rather minor optimization might not be worth dealing with these
                            effects. On the other hand, your application should already be able to handle failed GENA
                            subscription renewals, or disappearing remote devices!
                        </p>

                    </div>
                </div>

                <div class="section" id="section.Android.Optimize.Discovery">
                    <div class="title">Configuring discovery</div>
                    <div class="content">

                        <p>
                            The most effective optimization is selective discovery of UPnP devices. Although the UPnP
                            service's network transport layer will keep running (threads are waiting and sockets are
                            bound) in the background, this feature allows you to drop discovery messages selectively and
                            quickly.
                        </p>

                        <p>
                            For example, if you are writing a control point, you can drop any received discovery message
                            if it doesn't advertise the service you want to control - you are not interested in any
                            other device. On the other hand if you only <em>provide</em> devices and services, all
                            discovery messages (except search messages for your services) can probably be dropped, you
                            are not interested in any remote devices and their services at all.
                        </p>

                        <p>
                            Discovery messages are selected and potentially dropped by Cling as soon as the UDP datagram
                            content is available, so no further parsing and processing is needed and CPU time/memory
                            consumption is significantly reduced while you keep the UPnP service running even in the
                            background on an Android handset.
                        </p>

                        <p>
                            To configure which services are supported by your control point application, override the
                            configuration and provide an array of <code>ServiceType</code> instances:
                        </p>

                        <a class="citation"
                           href="javacode://org.fourthline.cling.demo.android.browser.BrowserUpnpService"
                           id="org.fourthline.cling.demo.android.browser.BrowserUpnpService_serviceType"
                           style="include:CLASS; exclude: REGISTRY;"/>

                        <p>
                            This configuration will ignore any advertisement from any device that doesn't also advertise
                            a <em>schemas-upnp-org:SwitchPower:1</em> service. This is what our control point can
                            handle, so we don't need anything else. If instead you'd return an empty array (the default
                            behavior), all services and devices will be discovered and no advertisements will be
                            dropped.
                        </p>

                        <p>
                            If you are not writing a control point but a server application, you can return
                            <code>null</code> in the <code>getExclusiveServiceTypes()</code> method. This will disable
                            discovery completely, now all device and service advertisements are dropped as soon as they
                            are received.
                        </p>

                    </div>
                </div>

            </div>
        </div>

    </div>
</div>
